package com.smartao.base.department;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.stereotype.Repository;

import com.smartao.base.Constant;
import com.smartao.core.dao.BaseEntityDao;

@Repository
public class DepartmentDaoImpl extends BaseEntityDao<Department, Long> implements DepartmentDao {
	
	@Override
	public void save(Department department){
		if(department.getParent()!=null){
			getSession().evict(department.getParent());
		}
		super.save(department);
	}
	
	@Override
	public void delete(Long id) {
		Department department = findOne(id);
		delete(department);
	}

	@Override
	public void delete(Department department) {
		Integer left = department.getLeftKey();
		Integer right = department.getRightKey();

		Integer delta = right - left + 1;
		Session session = getSession();
		// 把该对象从一级缓存移除；
		session.evict(department);

		session.createSQLQuery(
				"DELETE from T_BASE_DEPARTMENT WHERE LEFT_KEY >=:pLeft AND RIGHT_KEY<=:pRight")
				.setInteger("pLeft", left).setInteger("pRight", right)
				.executeUpdate();
		
		session.createSQLQuery(
				"UPDATE T_BASE_DEPARTMENT SET LEFT_KEY = LEFT_KEY - :delta WHERE LEFT_KEY> :pLeft")
				.setInteger("delta", delta).setInteger("pLeft", left)
				.executeUpdate();
		
		session.createSQLQuery(
				"UPDATE T_BASE_DEPARTMENT SET RIGHT_KEY = RIGHT_KEY - :delta WHERE RIGHT_KEY> :pRight")
				.setInteger("delta", delta).setInteger("pRight", right)
				.executeUpdate();
		
	}
	
	@Override
	public Department findRoot() {
		String hql = "FROM Department where dimension.code = :code and parent is null";
		return (Department) getSession()
				.createQuery(hql)
				.setString("code", Constant.SELECTITEM_DEPARTMENT_DIMENTION_ADMIN)
				.uniqueResult();
	}
	
	@Override
	public Department findRoot(Long dimensionId) {
		return findUnique(Restrictions.isNull("parent"), Restrictions.eq("dimension.id", dimensionId));
	}

	@Override
	public List<Department> getAllChild(Department department) {
		return find(Restrictions.between("leftKey", department.getLeftKey(), department.getRightKey()));
	}
	
	@Override
	public List<Department> findByParent(Long pid) {
		return findBy("parent.id", pid);
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Department> getPath(Department department) {
		Criteria criteria = createCriteria();
		criteria.add(Restrictions.lt("leftKey", department.getLeftKey()));
		criteria.add(Restrictions.gt("rightKey", department.getRightKey()));
		criteria.addOrder(Order.asc("leftKey"));
		return criteria.list();
	}

	@Override
	public Long getDierctChildCount(Long pid) {
		String hqlQuery = "SELECT COUNT(*) FROM Department WHERE ";
		hqlQuery += pid == null ? "PARENT IS NULL" : "PARENT.ID = ?";
		return findUnique(hqlQuery, pid);
	}
	
	@Override
	public void batchUpdateLeftRightKey(int pRight){
		Session session = getSession();
		session.createSQLQuery(
				"UPDATE T_BASE_DEPARTMENT SET RIGHT_KEY = RIGHT_KEY + 2 WHERE RIGHT_KEY>=:pRight")
				.setInteger("pRight", pRight).executeUpdate();
		session.flush();
		session.createSQLQuery(
				"UPDATE T_BASE_DEPARTMENT SET LEFT_KEY = LEFT_KEY + 2 WHERE LEFT_KEY>=:pRight")
				.setInteger("pRight", pRight).executeUpdate();
		session.flush();
	}
	
	@Override
	public void batchUpdateRightKey(Integer key, Long dimensionId) {
		String hqlUpdate = "UPDATE Department SET RIGHT_KEY = RIGHT_KEY + 2 WHERE RIGHT_KEY >= :key and DIMENSION=:dimensionId";
		getSession().createQuery(hqlUpdate).setInteger("key", key).setLong("dimensionId", dimensionId).executeUpdate();
	}

	@Override
	public void batchUpdateLeftKey(Integer key, Long dimensionId) {
		String hqlUpdate = "UPDATE Department SET LEFT_KEY = LEFT_KEY + 2 WHERE LEFT_KEY >= :key  and DIMENSION=:dimensionId";
		getSession().createQuery(hqlUpdate).setInteger("key", key).setLong("dimensionId", dimensionId).executeUpdate();

	}
}
